package com.qujia.station.controller;

import com.alibaba.fastjson.JSONObject;
import com.qujia.common.constant.HttpStatus;
import com.qujia.common.core.controller.BaseController;
import com.qujia.common.core.domain.AjaxResult;
import com.qujia.common.core.domain.entity.SysUser;
import com.qujia.common.core.page.TableDataInfo;
import com.qujia.common.exception.BaseException;
import com.qujia.common.utils.DateUtils;
import com.qujia.common.utils.SecurityUtils;
import com.qujia.common.utils.poi.ExcelUtil;
import com.qujia.station.domain.CardBatch;
import com.qujia.station.domain.PhysicalCard;
import com.qujia.station.domain.dto.PhysicalCardListDto;
import com.qujia.station.domain.dto.PhysicalCardSecretKeyDto;
import com.qujia.station.enums.PhysicalCardTypeEnum;
import com.qujia.station.service.CardBatchService;
import com.qujia.station.service.IPhysicalCardService;
import com.qujia.station.utils.RegexUtils;
import com.qujia.station.utils.SnowFlakeUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.*;

/**
 * 实体卡信息
 * */

@RestController
@RequestMapping("/physicalCard")
@Slf4j
@Api(value = "实体卡信息接口",description = "实体卡信息接口")
public class PhysicalCardController extends BaseController {

    @Autowired
    private IPhysicalCardService physicalCardService;

    // 实体卡A密钥，16进制,必须是12位
    @Value("${physicalCard.secretKeyA}")
    private String SECRET_KEY_A;

    //实体卡B密钥，16进制,必须是12位
    @Value("${physicalCard.secretKeyB}")
    private String SECRET_KEY_B;

    @Autowired
    private CardBatchService cardBatchService;

    /**
     * 查询单个卡信息
     * */
    @GetMapping("/get")
    @ApiOperation(value = "查询单个卡信息",response = PhysicalCard.class)
    public AjaxResult getByNo(@RequestParam("physicalCardNo") String physicalCardNo){
        if(StringUtils.isEmpty(physicalCardNo)){
            return AjaxResult.error("请求参数不存在");
        }
        physicalCardNo = com.qujia.common.utils.StringUtils.trim(physicalCardNo);
        log.info("查询单个卡信息请求参数：[{}]",physicalCardNo);
        SysUser user = SecurityUtils.getLoginUser().getUser();
        Long enterpriseId = user.getEnterpriseId();

        PhysicalCard physicalCard = physicalCardService.selectPhysicalCard(physicalCardNo);
        if(Objects.isNull(physicalCard)){
            return AjaxResult.error(200,"实体卡不存在");
        }
        if(Objects.nonNull(enterpriseId) && !enterpriseId.equals(physicalCard.getEnterpriseId())){
            physicalCard.setIsStrange(0);
            return AjaxResult.success(physicalCard);
        }
        physicalCard.setIsStrange(1);
        return AjaxResult.success(physicalCard);
    }

    /**
     * 新增实体卡  复制实体卡
     * */
    @PostMapping("/add")
    @ApiOperation(value = "新增实体卡、复制实体卡", response = PhysicalCardSecretKeyDto.class)
    public AjaxResult addPhysicalCard(@RequestBody PhysicalCard physicalCard){
        if(Objects.isNull(physicalCard)){
            return AjaxResult.error("请求参数不存在");
        }
        isCheck(physicalCard);
        if(Objects.nonNull(physicalCard.getPhysicalCardAmount())){
            long length = String.valueOf(physicalCard.getPhysicalCardAmount()).length();
            if(length >11){
                return AjaxResult.error("充值面额太大");
            }
        }
        if(Objects.isNull(physicalCard.getPhysicalCardAmount())){
            physicalCard.setPhysicalCardAmount(BigDecimal.ZERO);
        }
        SysUser user = SecurityUtils.getLoginUser().getUser();
        physicalCard.setCreateBy(user.getUserName());
        physicalCard.setSecretKeyA(SECRET_KEY_A);
        physicalCard.setSecretKeyB(SECRET_KEY_B);
        String physicalCardNo = physicalCardService.addPhysicalCard(physicalCard);

        PhysicalCardSecretKeyDto physicalCardSecretKeyDto = new PhysicalCardSecretKeyDto();
        physicalCardSecretKeyDto.setPhysicalCardNo(physicalCardNo);
        physicalCardSecretKeyDto.setSecretKeyA(SECRET_KEY_A);
        physicalCardSecretKeyDto.setSecretKeyB(SECRET_KEY_B);
        return AjaxResult.success(physicalCardSecretKeyDto);
    }

    /**查询实体卡列表*/
    @GetMapping("/list")
    @ApiOperation(value = "查询实体卡列表",response = PhysicalCard.class)
    public TableDataInfo getPhysicalCardList(PhysicalCardListDto physicalCardDto){
        // 油企账号查询 只能看本油企
        Long enterpriseId = SecurityUtils.getLoginUser().getUser().getEnterpriseId();
        if(Objects.nonNull(enterpriseId)) {
            physicalCardDto.setEnterpriseId(enterpriseId);
        }

        Long stationId = SecurityUtils.getLoginUser().getUser().getStationId();
        if(Objects.nonNull(stationId)){
            physicalCardDto.setStationId(String.valueOf(stationId));
        }

        startPage();
        List<PhysicalCard> physicalCardList = physicalCardService.selectPhysicalCardList(physicalCardDto);
        log.info("查询实体卡列表PhysicalCardController.getPhysicalCardList:[{}]", JSONObject.toJSONString(physicalCardList));
        return getDataTable(physicalCardList);
    }

    /**修改覆盖实体卡  不允许修改面额充值*/
    @PostMapping("/update")
    @ApiOperation(value = "修改覆盖实体卡、不允许修改面额充值", response = PhysicalCardSecretKeyDto.class)
    public AjaxResult updatePhysicalCard(@RequestBody PhysicalCard physicalCard){
        if(Objects.isNull(physicalCard) || StringUtils.isEmpty(physicalCard.getPhysicalCardNo())){
            return AjaxResult.error("请求参数异常");
        }
        physicalCard.setPhysicalCardNo(com.qujia.common.utils.StringUtils.trim(physicalCard.getPhysicalCardNo()));
        log.info("修改覆盖实体卡 请求参数：[{}]",JSONObject.toJSONString(physicalCard));
        isCheck(physicalCard);
        SysUser user = SecurityUtils.getLoginUser().getUser();
        physicalCard.setUpdateBy(user.getUserName());
        int num = physicalCardService.updateAdminPhysicalCard(physicalCard);
        if(num > 0){
            PhysicalCardSecretKeyDto physicalCardSecretKeyDto = new PhysicalCardSecretKeyDto();
            physicalCardSecretKeyDto.setPhysicalCardNo(physicalCard.getPhysicalCardNo());
            physicalCardSecretKeyDto.setSecretKeyA(SECRET_KEY_A);
            return AjaxResult.success(physicalCardSecretKeyDto);
        } else {
            return AjaxResult.error("修改信息失败");
        }
    }

    /** 批量修改实体卡状态为 冻结、注销状态*/
    @PostMapping("/update/status")
    @ApiOperation("批量修改实体卡状态为 冻结、注销状态,修改实体卡写卡状态")
    public AjaxResult updatePhysicalCardStatus(@RequestBody List<PhysicalCard> physicalCardList){
        if(CollectionUtils.isEmpty(physicalCardList)){
            return AjaxResult.error("请求参数异常");
        }
        SysUser user = SecurityUtils.getLoginUser().getUser();

        physicalCardList.stream().forEach(physicalCard -> {
            if(Objects.nonNull(physicalCard) && StringUtils.isNotEmpty(physicalCard.getPhysicalCardNo())){
                physicalCard.setUpdateBy(user.getUserName());
                int num = physicalCardService.updatePhysicalCardStatus(physicalCard);
                if(num <= 0){
                    log.info("实体卡修改状态PhysicalCardController.updatePhysicalCardStatus:[{}] 失败",JSONObject.toJSONString(physicalCard));
                }
            }
        });

        return AjaxResult.success();
    }


    /**
     * 获取密钥
     * */
    @GetMapping("/getSecretKey")
    @ApiOperation(value = "获取密钥",response = Map.class)
    public AjaxResult getSecretKey(){
        Map<String,Object> map = new HashMap<>();
        map.put("secretKeyA",SECRET_KEY_A);
        map.put("secretKeyB",SECRET_KEY_B);
        return AjaxResult.success(map);
    }


    /**
     * 返回生产实体卡号
     * */
    @GetMapping("/createNo")
    @ApiOperation(value = "获取实体卡号",response = PhysicalCardSecretKeyDto.class)
    public AjaxResult createNo(){
        long physicalCardNo = SnowFlakeUtil.getDefaultSnowFlakeId();
        PhysicalCardSecretKeyDto physicalCardSecretKeyDto = new PhysicalCardSecretKeyDto();
        physicalCardSecretKeyDto.setPhysicalCardNo(String.valueOf(physicalCardNo));
        physicalCardSecretKeyDto.setSecretKeyA(SECRET_KEY_A);
        physicalCardSecretKeyDto.setSecretKeyB(SECRET_KEY_B);
        return AjaxResult.success(physicalCardSecretKeyDto);
    }

    /**参数校验*/
    private void isCheck(PhysicalCard physicalCard){
        log.info("实体卡参数校验 isCheck：[{}]",JSONObject.toJSONString(physicalCard));
        if(Objects.isNull(physicalCard.getEnterpriseId())){
            throw new BaseException("请选择油企");
        }
        if(StringUtils.isEmpty(physicalCard.getStationId())){
            throw new BaseException("请选择油站");
        }
        if(StringUtils.isEmpty(physicalCard.getPhysicalCardName())){
            throw new BaseException("请输入卡名称");
        }
        if(physicalCard.getPhysicalCardName().length() > 20){
            throw new BaseException("输入卡名称不要超过20个字符");
        }

        if(StringUtils.isEmpty(physicalCard.getUserName())){
            throw new BaseException("请输入持卡人");
        }
        if(physicalCard.getUserName().length() > 20){
            throw new BaseException("输入持卡人姓名不要超过20个字符");
        }
        if(StringUtils.isEmpty(physicalCard.getUserPhone())){
            throw new BaseException("请输入手机号");
        }
        //手机号校验
        if(!RegexUtils.isPhoneNum(physicalCard.getUserPhone())){
            throw new BaseException("请输入正确的手机号");
        }
        if(StringUtils.isNotEmpty(physicalCard.getUserCompany()) && physicalCard.getUserCompany().length() > 20){
            throw new BaseException("输入企业名称不要超过20个字符");
        }
    }

    /**
     * 生成批次号的时候，空卡已经生成
     *
     */
    @PostMapping("/batch/save")
    @ApiOperation(value = "保存批次信息", httpMethod = "POST")
    public AjaxResult addCardBatch(@RequestBody CardBatch cardBatch){
        if(Objects.isNull(cardBatch)){
            return AjaxResult.error("请求参数为空");
        }
        if(StringUtils.isEmpty(cardBatch.getPhysicalCardType())){
            return AjaxResult.error("请选择实体卡类型");
        }
        if(PhysicalCardTypeEnum.DEK.getValue().equals(cardBatch.getPhysicalCardType())){
            if(Objects.isNull(cardBatch.getPhysicalCardAmount())){
                return AjaxResult.error("定额卡需要输入金额");
            }
            if(cardBatch.getPhysicalCardAmount().compareTo(BigDecimal.ZERO) <= 0){
                return AjaxResult.error("定额卡金额需要大于0");
            }
        }
        if(Objects.isNull(cardBatch.getCardNum()) || Objects.isNull(cardBatch.getWriteNum()) ){
            return AjaxResult.error("请求参数没有卡数量");
        }
        if((cardBatch.getCardNum() + cardBatch.getWriteNum()) >= 100000){
            return AjaxResult.error("新增批次卡数量太多");
        }
        if(cardBatch.getCardNum() <= 0){
            return AjaxResult.error("发卡数量请大于0");
        }
        if(cardBatch.getWriteNum() < 0){
            return AjaxResult.error("起始序号请大于0");
        }
        // 生成批次号 20231101
        cardBatch.setBatchNo(getBatchNo(cardBatch));
        int i = cardBatchService.saveCardBatch(cardBatch);
        if(i <= 0){
            return AjaxResult.error("保存批次号失败");
        }

        //写卡号
        CardBatch newCardBatch = cardBatchService.selectCardBatch(cardBatch.getBatchNo(),cardBatch.getPhysicalCardType());
        cardBatch.setId(newCardBatch.getId());
        physicalCardService.createEmptyCard(cardBatch);
        return AjaxResult.success("新增批次号成功");
    }

    // 生成批次号 20231101
    private String getBatchNo(CardBatch cardBatch){
        String batchNo = "";
        String time = DateUtils.parseDateToStr(DateUtils.YYYYMM,new Date());
        CardBatch cardBatchLast = cardBatchService.selectCardBatchLastByType(cardBatch);
        if(Objects.isNull(cardBatchLast)){
            batchNo = time + "01";
            return batchNo;
        }
        String lastBatchNo = cardBatchLast.getBatchNo();
        if(time.equals(lastBatchNo.substring(0,6))){
            int num =Integer.valueOf(lastBatchNo.substring(6));
            num  = num + 1;
            if(num >= 100){
                throw new BaseException("本月批次号已经封顶，请下月再创建");
            }
            String format = String.format("%02d", num);
            return time + format;
        }
        return time + "01";
    }

    @PostMapping("/batch/list")
    @ApiOperation(value = "查询批次信息列表", httpMethod = "POST")
    public TableDataInfo selectCardBatchList(@RequestBody CardBatch cardBatch){
        if(Objects.isNull(cardBatch) || StringUtils.isEmpty(cardBatch.getPhysicalCardType())){
            TableDataInfo rspData = new TableDataInfo();
            rspData.setCode(HttpStatus.ERROR);
            rspData.setMsg("请求参数异常");
            rspData.setRows(null);
            rspData.setTotal(0l);
            return rspData;
        }
        startPage();
        log.info("selectCardBatchList 请求参数：[{}]", JSONObject.toJSONString(cardBatch));
        List<CardBatch> cardBatchList = cardBatchService.selectCardBatchList(cardBatch);
        if(CollectionUtils.isEmpty(cardBatchList)){
            TableDataInfo rspData = new TableDataInfo();
            rspData.setCode(HttpStatus.SUCCESS);
            rspData.setMsg("暂时无数据");
            rspData.setRows(null);
            rspData.setTotal(0l);
            return rspData;
        }
        log.info("selectCardBatchList 响应结果：[{}]", cardBatchList.size());
        return getDataTable(cardBatchList);
    }

    @PostMapping("/batch/update")
    @ApiOperation(value = "修改已写数量", httpMethod = "POST")
    public AjaxResult updateCardBatch(@RequestBody CardBatch cardBatch){
        if(Objects.isNull(cardBatch)){
            return AjaxResult.error("编辑批次号信息不能为空");
        }

        log.info("updateCardBatch 请求参数：[{}]", JSONObject.toJSONString(cardBatch));
        int i = cardBatchService.updateCardBatch(cardBatch);
        if(i <= 0){
            return AjaxResult.error("编辑批次号信息失败");
        }
        return AjaxResult.success("编辑批次号信息成功");
    }

    @GetMapping("/batch/delete")
    @ApiOperation(value = "删除批次信息", httpMethod = "GET")
    public AjaxResult deleteCardBatch(@RequestParam("id") Long id){
        if(Objects.isNull(id)){
            return AjaxResult.error("删除批次信息请求参数不能为空");
        }

        log.info("deleteCardBatch 请求参数：[{}]", id);
        int i = cardBatchService.deleteCardBatch(id);
        if(i <= 0){
            return AjaxResult.error("删除批次信息失败");
        }
        return AjaxResult.success("删除批次信息成功");
    }

    /**
     * 导出卡号
     * */
    @GetMapping("/export/physicalCardNo")
    @ApiOperation(value = "导出卡号",httpMethod = "GET")
    public AjaxResult exportPhysicalCardNo(@RequestParam("id") Long id){
        if(Objects.isNull(id)){
            return AjaxResult.error("请求参数异常");
        }
        List<PhysicalCard> physicalCardList = physicalCardService.selectPhysicalCardListByBatchId(String.valueOf(id));
        ExcelUtil<PhysicalCard> util = new ExcelUtil<PhysicalCard>(PhysicalCard.class);
        return util.exportExcel(physicalCardList, "实体卡卡号");
    }


    /**
     * 判断是否可以写卡
     * */
    @GetMapping("/judge/card")
    @ApiOperation(value = "判断是否可以写卡",httpMethod = "GET")
    private AjaxResult judgeCard(@RequestParam("physicalCardNo") String physicalCardNo){
        if(StringUtils.isEmpty(physicalCardNo)){
            return AjaxResult.error("请求参数异常");
        }
        physicalCardNo = com.qujia.common.utils.StringUtils.trim(physicalCardNo);
        log.info("判断是否可以写卡请求参数：[{}]",physicalCardNo);
        Boolean result = physicalCardService.judgePhysicalCard(physicalCardNo);
        if(Boolean.TRUE.equals(result)){
            return AjaxResult.success("可以写卡", true);
        } else {
            return AjaxResult.error("此卡不能重复写卡",false);
        }
    }

    /**
     * 查询 一批次中第一个未写卡成功的卡号
     * */
    @GetMapping("/batch/firstNum")
    @ApiOperation(value = "第一个未写卡成功的卡号",httpMethod = "GET")
    private AjaxResult firstNumBatch(@RequestParam("id") Long id){
        if(Objects.isNull(id)){
            return AjaxResult.error("请求参数异常");
        }
        PhysicalCard physicalCard = physicalCardService.selectFirstNumByBatchId(String.valueOf(id));
        if(Objects.isNull(physicalCard)){
            return AjaxResult.error("此批次没有卡");
        }
        return AjaxResult.success(physicalCard);
    }

    /**
     * 注销列表
     * */
    @PostMapping("/card/withdraw/list")
    @ApiOperation(value = "注销列表",httpMethod = "POST")
    public TableDataInfo withdrawList(@RequestBody PhysicalCardListDto physicalCardListDto){
        log.info("withdrawList请求参数：[{}]",JSONObject.toJSONString(physicalCardListDto));

        startPage();
        List<PhysicalCard> physicalCardList = physicalCardService.selectWithdrawList(physicalCardListDto);
        return getDataTable(physicalCardList);
    }

}
